/* Predictor_traits.h
 *
 *	Copyright (C) 2008 CRIMERE
 *	Copyright (C) 2008 Jean-Marc Mercier
 *	
 *	This file is part of OTS (optimally transported schemes), an open-source library
 *	dedicated to scientific computing. http://code.google.com/p/optimally-transported-schemes/
 *
 *	CRIMERE makes no representations about the suitability of this
 *	software for any purpose. It is provided "as is" without express or
 *	implied warranty.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *
 */
#include <src/miscellaneous/OS_basic.h>
#include <src/data/Operators.h>


#if !defined(_PredictorTraits_)
#define _PredictorTraits_
/*
 Base behaviour for all Predictor conditions
*/
template <class TimeOperator > 
struct Predictor_traits {
	typedef typename TimeOperator						time_operator_type;
	typedef typename time_operator_type::argument_type	argument_type;
	typedef typename time_operator_type::time_type		time_type;
	typedef typename time_operator_type::result_type	result_type;
};
/*
 Base behaviour for Crank Nicolson predictors. 
 Up to now, the most general case use :
 an iteration of the Crank Nicolson fixed point resolution initial condition iterate
 the Operator applied to this iteration condition operator_iterate
 the next iteration of the Crank Nicolson fixed point algorithm next_iterate
 the Operator applied to the the next iteration operator_next_iterate
*/

template <class TimeOperator > 
struct CrankNicolsonPredictor_traits : public Predictor_traits<TimeOperator>{
	virtual bool operator()	(argument_type iterate, argument_type operator_iterate, argument_type next_iterate, argument_type operator_next_iterate) const = 0;
};
/*
	Standard condition for classical finite difference operators :

	Crank Nicolson algorithm convergence takes place if the relative \ell_2 error norm of each iterate is less than 1%.
*/
template <class TimeOperator > 
struct CrankNicolsonGenericPredictor : public CrankNicolsonPredictor_traits<TimeOperator>{
	public : 
		virtual bool operator()	(argument_type iterate, argument_type operator_iterate, argument_type next_iterate, argument_type operator_next_iterate) const {
			OS_double breakpoint1 = jmmath::norm22(iterate - next_iterate);
			OS_double breakpoint2 = jmmath::norm22(iterate);
			return breakpoint1/(1.+breakpoint2) < 1e-4;
		};
	};
/*
	This predictor is a very strong convergence conditions. It is used to control
	weakly consistent operator (like particles ones, see for instance the Cauchy problem for heat equation described
	by the classes Cauchy_Delta_p) :

	Crank Nicolson algorithm convergence takes place if the relative \ell_2 error of each operator iteration is less than 1%.
*/
template <class TimeOperator > 
struct CrankNicolsonOperatorPredictor : public CrankNicolsonPredictor_traits<TimeOperator>{
	public : 
		virtual bool operator()	(argument_type iterate, argument_type operator_iterate, argument_type next_iterate, argument_type operator_next_iterate) const {
			OS_double breakpoint1 = jmmath::norm22(operator_iterate - operator_next_iterate);
			OS_double breakpoint2 = jmmath::norm22(operator_iterate);
			return breakpoint1/(1.+breakpoint2) < 1e-4;
		};
	};


#endif
